package com.googlecode.afx.splash.impl;

import com.googlecode.afx.splash.AFXSplashScreen;

import javafx.animation.FadeTransition;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import javafx.concurrent.Worker;

/**
 * Default splash screen implementation used by <tt>com.googlecode.afx.AFXApplication</tt>.
 * 
 * @author MartinKoster
 *
 */
public class AFXSplashScreenImpl implements AFXSplashScreen {

	private static final int SPLASH_WIDTH = 400;
	private static final int SPLASH_HEIGHT = 300;

	private String splashImage;
	private String title;
	
	/**
	 * Default constructor.
	 */
	public AFXSplashScreenImpl() {
	}

	/**
	 * Constructor that accepts a title message and a splash image URL.
	 * 
	 * @param title
	 * @param splashImage
	 */
	public AFXSplashScreenImpl(String title, String splashImage) {
		this.title = title;
		this.splashImage = splashImage;
	}	
	
	public void showSplashScreen(Task<?> task) {
		Stage splash = this.createSplashStage(task);
		splash.show();
	}

	protected Stage createSplashStage(Task<?> task) {

		ProgressBar loadProgress = new ProgressBar();
		loadProgress.setPrefWidth(SPLASH_WIDTH - 20);
		Label progressText = new Label("Loading...");
		VBox splashLayout = new VBox();
		splashLayout.setAlignment(Pos.CENTER);
		
		if(this.title != null) {
			splashLayout.getChildren().add(new Label(this.title));
		}
		
		if(this.splashImage != null) {
			ImageView imageView = new ImageView(new Image(this.splashImage));
			splashLayout.getChildren().add(imageView);
		}
		
		splashLayout.getChildren().addAll(loadProgress, progressText);
		progressText.setAlignment(Pos.CENTER);

		splashLayout.setStyle("-fx-padding: 5; " + "-fx-background-color: cornsilk; " + "-fx-border-width:5; "
				+ "-fx-border-color: " + "linear-gradient(" + "to bottom, " + "chocolate, " + "derive(chocolate, 50%)"
				+ ");");
		splashLayout.setEffect(new DropShadow());

		Scene splashScene = new Scene(splashLayout);
		Stage splashStage = new Stage(StageStyle.UNDECORATED);

		progressText.textProperty().bind(task.messageProperty());
		loadProgress.progressProperty().bind(task.progressProperty());
		task.stateProperty().addListener((observableValue, oldState, newState) -> {
			if (newState == Worker.State.SUCCEEDED) {
				loadProgress.progressProperty().unbind();
				loadProgress.setProgress(1);
				splashStage.toFront();
				FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout);
				fadeSplash.setFromValue(1.0);
				fadeSplash.setToValue(0.0);
				fadeSplash.setOnFinished(actionEvent -> splashStage.hide());
				fadeSplash.play();
			} 
		});
		
		final Rectangle2D bounds = Screen.getPrimary().getBounds();
		splashStage.setScene(splashScene);
		splashStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
		splashStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);

		return splashStage;
	}
}
